
-- | The module "Representation" contains all data types for
-- representing a Game.



module Environment.Representation where

import Data.Vector as V

-- ############# Environment Representation #############

-- | A Game consists of the opponent's and proponent's environment as well as the number of turns.
data Game = Game {prop::Environment,
                  op::Environment}deriving(Show)

-- | An Environment is a Vector of Slots (For efficiency reasons)
type Environment = Vector Slot

-- | A Slot is a tuple. The first entry is the Field's Life,
--   the second is the corresponding Field.
type Slot = (Life, Field)

-- | Representation of a Slot's Life. The Life of a Field is in the range of -1 to 65535 and the integer of a Slot is in the range of 0 to 65535.
newtype Life = Life { lifeVal :: Int }
  deriving (Eq, Ord, Show)

-- | A Field of Slot is either an integer, a Card, an Application of two Fields, or an Error.
data Field = VInt Int   -- ^ Value of a Field, ranging from 0 to 65535
           | VCard Card -- ^ Card of a Field
           | VApp Field Field  -- ^ A Stack of Fields, which are not evaluated immediately.
           | VError     -- ^ Error state.
           deriving(Eq,Show)

-- | Card representation by a new data structure
data Card = I   -- ^ Identity Card
          |Zero -- ^ Zero Card
          |Succ -- ^ Succ Card
          |Dbl  -- ^ Dbl Card
          |Get  -- ^ Get card
          |Put  -- ^ Put Card
          |S    -- ^ S Card
          |K    -- ^ K Card
          |Inc  -- ^ Inc Card
          |Dec  -- ^ Dec Card
          |Attack -- ^ Attack Card
          |Help   -- ^ Help Card
          |Copy   -- ^ Copy Card
          |Revive -- ^ Revive Card
          |Zombie -- ^ Zombie Card
             deriving (Eq, Show)

-- | An action is an Int, indicating in which way a Card is applied (1=left, 2=right), the played Card, and the index (0-255) of the Slot
-- the Card is applied to.
type Action = (Int,Card,Int)

-- | Translate a Card into the corresponding string.
card2Name :: Card
          -> String
card2Name I       = "I"
card2Name Zero    = "zero"
card2Name Succ    = "succ"
card2Name Dbl     = "dbl"
card2Name Get     = "get"
card2Name Put     = "put"
card2Name S       = "S"
card2Name K       = "K"
card2Name Inc     = "inc"
card2Name Dec     = "dec"
card2Name Attack  = "attack"
card2Name Help    = "help"
card2Name Copy    = "copy"
card2Name Revive  = "revive"
card2Name Zombie  = "zombie"

-- | Translate a String into its corresponding Card.
name2Card :: String -> Card
name2Card "I"        =  I
name2Card "zero"     =  Zero
name2Card "succ"     =  Succ
name2Card "dbl"      =  Dbl
name2Card "get"      =  Get
name2Card "put"      =  Put
name2Card "S"        =  S
name2Card "K"        =  K
name2Card "inc"      =  Inc
name2Card "dec"      =  Dec
name2Card "attack"   =  Attack
name2Card "help"     =  Help
name2Card "copy"     =  Copy
name2Card "revive"   =  Revive
name2Card "zombie"   =  Zombie

-- | A smart constructor for Life, doing bound checking.
mkLife :: Int -> Life
mkLife n
  | n > 65535 =  Life 65535
  | n < 0 =  Life 0
  | otherwise =  Life n

-- | A smart constructor for a Field's value.
mkValue::Int -> Int
mkValue n
       | n <= 0 =  0
       | n > 0 && n <= 65535 =  n
       | otherwise =  65535

-- | initialises the Environment
initEnv::Environment
initEnv = V.fromList [(mkLife 10000, VCard I)| _<-[1..256]]

-- | Initialises a Game
initGame::Game
initGame = Game {prop = initEnv,
                 op = initEnv}

